package com.lagou.edu.bean;

import com.google.common.base.Strings;
import com.lagou.edu.anno.Component;
import com.lagou.edu.anno.Controller;
import com.lagou.edu.anno.Repository;
import com.lagou.edu.anno.Service;
import com.lagou.edu.utils.JsonUtils;
import org.reflections.Reflections;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 包扫描
 * @author wsz
 * @date 2021/10/18 20:04
 **/
public class PackageScan {

    private String packageName;

    // 存放包内所有class
    private Set<Class> allClass = new LinkedHashSet<>();

    // 存放特定注解的
    private Set<BeanDefinition> annoClass = new HashSet<>();

    public PackageScan(String packageName) {
        this.packageName = packageName;
    }

    public void initDefinition() {
        doScanAll();
        doScanAnno();
    }

    /**
     * 使用guava工具类
     * 扫描包内的class
     */
    private void doScanAll() {
        Reflections reflections = new Reflections(packageName);
        // 已经把基于MyComponent的获取到了，如@Repository/@Service/@Controller/@Autowired
        allClass.addAll(reflections.getTypesAnnotatedWith(Component.class));
    }

    /**
     * 获取自定义注解的class
     */
    private void doScanAnno() {
        for (Class aClass : allClass) {
            if (aClass.isAnnotation() || aClass.isInterface()) continue;

            Controller controller = (Controller) aClass.getAnnotation(Controller.class);
            if (controller != null) {
                initDefinition(aClass, controller.value(), controller.lazyInit(), controller.singleton());
            }

            Service service = (Service) aClass.getAnnotation(Service.class);
            if (service != null) {
                initDefinition(aClass, service.value(), service.lazyInit(), service.singleton());
            }

            Repository repository = (Repository) aClass.getAnnotation(Repository.class);
            if (repository != null) {
                initDefinition(aClass, repository.value(), repository.lazyInit(), repository.singleton());
            }

            Component component = (Component) aClass.getAnnotation(Component.class);
            if (component != null) {
                initDefinition(aClass, component.value(), component.lazyInit(), component.singleton());
            }
        }
    }

    /**
     * 初始化BeanDefinition
     * @param aClass
     * @param value
     */
    private void initDefinition(Class aClass, String value, boolean lazyInit, boolean singleton) {
        BeanDefinition definition = new BeanDefinition();

        // bean id命名规则
        String id = Strings.isNullOrEmpty(value) ? aClass.getSimpleName() : value;
        definition.setId(JsonUtils.toCaseStr(id));
        definition.setLazyInit(lazyInit);
        definition.setSingleton(singleton);
        definition.setTarget(aClass);

        // FIXME 把接口信息也同步加入
        Set<String> names = new HashSet<>();
        Class[] interfaces = aClass.getInterfaces();
        for(Class cl : interfaces) {
            names.add(JsonUtils.toCaseStr(cl.getSimpleName()));
        }
        definition.setInterfacesNames(names);

        annoClass.add(definition);
    }

    public Set<BeanDefinition> getBeanDefinition() {
        return annoClass;
    }

    public BeanDefinition getBeanDefinition (String name) {
        for (BeanDefinition b : annoClass) {
            if (b.getId().equals(name)) {
                return b;
            }
        }
        return null;
    }

}
